#include <string.h>
#include <stdlib.h>
#include "link_queue.h"

Status linkqueue_init(link_queue *q, size_t struct_size)
{
	q->front = q->rear = (qnode *)malloc(sizeof(qnode));
	if(!q->front) exit(OVERFLOW);
	q->front->next = NULL;
	q->struct_size = struct_size;
	return SUCCESS;
}

Status linkqueue_destroy(link_queue *q)
{
	while(q->front){
		q->rear = q->front->next;
		free(q->front->data);
		free(q->front);
		q->front = q->rear;
	}
	return SUCCESS;
}

Status linkqueue_clear(link_queue *q)
{
	qnode *p = q->front->next;
	while(p){
		free(p->data);
		free(p);
		p = p->next;
	}
	q->rear = q->front;
	q->front->next = NULL;
	return SUCCESS;
}

size_t linkqueue_length(link_queue q)
{
	qnode *p = q.front;
	size_t i = 0;
	while(p = p->next) i++;
	return i;
}

Status linkqueue_gethead(link_queue q, void * e)
{
	if(linkqueue_empty(q)) return ERROR;
	memcpy(e, q.front->next->data, q.struct_size);
	return SUCCESS;
}

Status linkqueue_enter(link_queue *q, const void *e)
{
	qnode *p = (qnode *) malloc(sizeof(qnode));
	if(!p) exit(OVERFLOW);
	p->data = malloc(q->struct_size);
	if(!p->data) exit(OVERFLOW);
	p->next = NULL;
	memcpy(p->data, e, q->struct_size);
	q->rear->next = p;
	q->rear = p;
	return SUCCESS;
}

Status linkqueue_delete(link_queue *q, void *e)
{
	qnode *p;
	if(linkqueue_empty(*q)) return ERROR;
	p = q->front->next;
	memcpy(e, p->data, q->struct_size);
	q->front->next = p->next;
	if(q->rear == p)
		q->rear = q->front;
	free(p->data);
	free(p);
	return SUCCESS;
}

Status linkqueue_traverse(link_queue q, Bool visit(const void *))
{
	qnode *p;
	p = q.front->next;
	while(p && visit(p->data))
		p = p->next;
	if(p) return ERROR;
	return SUCCESS;
}
